package com.feng.chat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.feng.chat.common.Common;
import com.feng.chat.common.Regex;
import com.feng.chat.controller.WebSocketSever;
import com.feng.chat.dto.*;
import com.feng.chat.entity.*;
import com.feng.chat.mapper.*;
import com.feng.chat.service.IUsersService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.feng.chat.utils.GetUserUtil;
import com.feng.chat.utils.IpUtil;
import com.feng.chat.utils.JwtUtil;
import com.feng.chat.utils.MD5;
import com.feng.chat.vo.EventTalkDataVO;
import com.feng.chat.vo.EventTalkVO;
import com.feng.chat.vo.LoginVO;
import com.feng.chat.vo.UsersVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;
import sun.management.resources.agent;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.net.UnknownHostException;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Pattern;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author dyf
 * @since 2022-05-31
 */
@Service
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements IUsersService {

    @Autowired
    private ArticleClassMapper articleClassMapper;

    @Autowired
    private TalkSessionMapper talkSessionMapper;

    @Autowired
    private TalkRecordsMapper talkRecordsMapper;

    @Autowired
    private TalkRecordsLoginMapper talkRecordsLoginMapper;

    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    private IpUtil ipUtil;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    /**
     * 用户登录
     *
     * @param request
     * @param userDTO
     * @return
     */
    @Override
    public Result login(HttpServletRequest request, UserDTO userDTO) {
        if (userDTO.getMobile() != null && !userDTO.getMobile().equals("")) {
            QueryWrapper<Users> mobileWrapper = new QueryWrapper<>();
            mobileWrapper.eq("mobile", userDTO.getMobile());
            Users user = getOne(mobileWrapper);
            String password = MD5.encrypt(userDTO.getPassword());
            if (user != null && user.getPassword().equals(password)) {
                TokenDTO tokenDTO = new TokenDTO();
                tokenDTO.setExpires_in(JwtUtil.expiresIn / 1000);
                tokenDTO.setAccess_token(JwtUtil.createToken(user.getId().toString()));
                tokenDTO.setType("Bearer");

//                try {
                    AddressDTO userAddress = ipUtil.getUserAddress(request);

                    QueryWrapper<TalkRecordsLogin> talkRecordsLoginQueryWrapper = new QueryWrapper<>();
                    talkRecordsLoginQueryWrapper.orderByDesc("id").last("LIMIT 1");
                    TalkRecordsLogin talkRecordsLogin = talkRecordsLoginMapper.selectOne(talkRecordsLoginQueryWrapper);

                    if (talkRecordsLogin == null || !talkRecordsLogin.getIp().equals(userAddress.getIp())) {
                        TalkRecords talkRecords = new TalkRecords();
                        talkRecords.setTalkType(1);
                        talkRecords.setMsgType(8);
                        talkRecords.setUserId(5);
                        talkRecords.setReceiverId(user.getId());
                        talkRecordsMapper.insert(talkRecords);

                        TalkRecordsLogin loginRecords = new TalkRecordsLogin();
                        loginRecords.setRecordId(talkRecords.getId());
                        loginRecords.setPlatform(request.getHeader("sec-ch-ua-platform"));
                        String agent = request.getHeader("User-Agent");
                        loginRecords.setAgent(agent);
                        loginRecords.setAddress(userAddress.getAddr());
                        loginRecords.setIp(userAddress.getIp());
                        loginRecords.setReason("非常用IP地址登录");
                        talkRecordsLoginMapper.insert(loginRecords);

                        KeepAlive keepAlive = new KeepAlive();
                        keepAlive.setEvent(Common.EVENT_TALK);

                        EventTalkVO eventTalkVO = new EventTalkVO();
                        eventTalkVO.setTalk_type(1);
                        eventTalkVO.setReceiver_id(talkRecords.getReceiverId());
                        eventTalkVO.setSender_id(5);

                        EventTalkDataVO eventTalkDataVO = new EventTalkDataVO();
                        eventTalkDataVO.setCreated_at(talkRecords.getCreatedAt().format(DateTimeFormatter.ofPattern(Common.LOCALDATETIME_FORMATER)));
                        eventTalkDataVO.setId(talkRecords.getId());
                        eventTalkDataVO.setIs_mark(talkRecords.getIsMark());
                        eventTalkDataVO.setIs_read(talkRecords.getIsRead());
                        eventTalkDataVO.setIs_revoke(talkRecords.getIsRevoke());
                        eventTalkDataVO.setMsg_type(talkRecords.getMsgType());
                        eventTalkDataVO.setReceiver_id(talkRecords.getReceiverId());
                        eventTalkDataVO.setTalk_type(talkRecords.getTalkType());
                        eventTalkDataVO.setUser_id(talkRecords.getUserId());

                        Users users = usersMapper.selectById(talkRecords.getUserId());
                        eventTalkDataVO.setAvatar(users.getAvatar());

                        LoginVO loginVO = new LoginVO();
                        loginVO.setReason(loginRecords.getReason());
                        loginVO.setPlatform(loginRecords.getPlatform());
                        loginVO.setIp(loginRecords.getIp());
                        loginVO.setAgent(loginRecords.getAgent());
                        loginVO.setAddress(loginRecords.getAddress());
                        loginVO.setCreated_at(loginRecords.getCreatedAt().format(DateTimeFormatter.ofPattern(Common.LOCALDATETIME_FORMATER)));

                        eventTalkDataVO.setLogin(loginVO);

                        eventTalkVO.setData(eventTalkDataVO);
                        keepAlive.setContent(eventTalkVO);

                        if (GetUserUtil.isOnLine(user.getId()) == 1) {
                            GetUserUtil.sendMessage(keepAlive, user.getId());
                        }
                    }

                /*} catch (UnknownHostException e) {
                    e.printStackTrace();
                }*/

                return Result.success(tokenDTO);
            }
        }
        return Result.fail();
    }

    /**
     * 用户注册
     *
     * @param userDTO
     * @return
     */
    @Override
    public Result register(UserDTO userDTO) {

        if (userDTO.getPassword() != null && !userDTO.getPassword().equals("")) {
            QueryWrapper<Users> mobileWrapper = new QueryWrapper<>();
            mobileWrapper.eq("mobile", userDTO.getMobile());
            Users user = getOne(mobileWrapper);
            if (user != null) {
                return Result.fail("该手机号已被注册！");
            } else {
                QueryWrapper<Users> nickNameWrapper = new QueryWrapper<>();
                nickNameWrapper.eq("nick_name", userDTO.getNickname());
                Users users = getOne(nickNameWrapper);
                if (users != null) {
                    return Result.fail("该昵称已被使用");
                } else {
                    Users users1 = new Users();
                    users1.setAvatar(Common.DEFAULT_AVATAR);
                    users1.setMobile(userDTO.getMobile());
                    users1.setNickName(userDTO.getNickname());
                    users1.setPassword(MD5.encrypt(userDTO.getPassword()));
                    save(users1);

                    ArticleClass articleClass = new ArticleClass();
                    articleClass.setClassName("默认分类");
                    articleClass.setUserId(users1.getId());
                    articleClass.setIsDefault(1);
                    articleClassMapper.insert(articleClass);

                    TalkSession talkSession = new TalkSession();
                    talkSession.setUserId(users1.getId());
                    talkSession.setReceiverId(5); //登陆助手机器人
                    talkSession.setIsRobot(1);
                    talkSessionMapper.insert(talkSession);

                    return Result.success("注册成功");
                }
            }
        }


        return Result.fail();
    }

    @Override
    public Result usersSetting(Integer id) {
        Users users = getById(id);
        SettingDTO settingDTO = new SettingDTO();
        Setting setting = new Setting();
        settingDTO.setSetting(setting);

        UsersVO usersVO = new UsersVO();
        usersVO.setUid(users.getId());
        usersVO.setMobile(users.getMobile());
        usersVO.setAvatar(users.getAvatar());
        usersVO.setNickname(users.getNickName());

        usersVO.setEmail(users.getEmail());
        usersVO.setGender(users.getGender());
        usersVO.setMotto(users.getMotto());
        usersVO.setIs_qiye(false);
        settingDTO.setUser_info(usersVO);
        return Result.success(settingDTO);
    }

    /**
     * 头像上传
     *
     * @param file
     * @return
     */
    @Override
    public Result avatar(MultipartFile file) {
        String path = "E:\\Desktop\\案例\\javaweb案例\\MyChat\\resource\\avatar\\";
        String oldFileName = file.getOriginalFilename();
        String suffix = oldFileName.substring(oldFileName.lastIndexOf(".") + 1);
        String newFileName = UUID.randomUUID().toString().replaceAll("-", "");
        newFileName = newFileName + "." + suffix;
        String url = "http://localhost:8081/avatar/" + newFileName;
        path = path + newFileName;
        File avatar = new File(path);
        if (!avatar.getParentFile().exists()) {
            avatar.getParentFile().mkdirs();
        }
        try {
            file.transferTo(avatar);
        } catch (IOException e) {
            return Result.fail();
        }
        Map<String, String> map = new HashMap<>();
        map.put("avatar", url);
        return Result.success(map);
    }

    /**
     * 个人详细信息
     *
     * @param uid
     * @return
     */
    @Override
    public Result usersDetail(Integer uid) {
        Users users = getById(uid);
        UsersDetailDTO usersDetailDTO = new UsersDetailDTO();
        BeanUtils.copyProperties(users, usersDetailDTO);
        usersDetailDTO.setNickname(users.getNickName());
        return Result.success(usersDetailDTO);
    }

    /**
     * 修改个人信息
     *
     * @param uid
     * @param avatar
     * @param gender
     * @param motto
     * @param nickname
     * @return
     */
    @Override
    public Result changeDetail(Integer uid, String avatar, Integer gender, String motto, String nickname) {
        Users users = getById(uid);
        users.setAvatar(avatar);
        users.setGender(gender);
        users.setMotto(motto);
        users.setNickName(nickname);
        updateById(users);
        return Result.success();
    }

    /**
     * 修改密码
     *
     * @param uid
     * @param new_password
     * @param old_password
     * @return
     */
    @Override
    public Result changePassword(Integer uid, String new_password, String old_password) {
        Users users = getById(uid);
        if (users != null) {
            if (users.getPassword().equals(MD5.encrypt(old_password))) {
                users.setPassword(MD5.encrypt(new_password));
                updateById(users);
                return Result.success("密码修改成功！");
            } else {
                return Result.fail("登录密码错误！");
            }
        } else {
            return Result.fail("该用户不存在！");
        }
    }

    /**
     * 绑定邮箱
     *
     * @param uid
     * @param email
     * @param email_code
     * @param password
     * @param session
     * @return
     */
    @Override
    public Result changeEmail(Integer uid, String email, String email_code, String password, HttpSession session) {
        if (email != null) {
//            String code = (String) session.getAttribute(email);
            //redis 获取验证码
            String code = (String) redisTemplate.opsForValue().get(email);

            if (code != null && code.equals(email_code)) {
                Users users = getById(uid);
                if (users != null && users.getPassword().equals(MD5.encrypt(password))) {
                    users.setEmail(email);
                    updateById(users);
                    //绑定成功后移除验证码
                    redisTemplate.delete(email);
                    return Result.success();
                } else {
                    return Result.fail("密码错误！");
                }
            } else {
                return Result.fail("验证码错误或验证码已失效！");
            }
        }
        return Result.fail("请输入邮箱！");
    }

    /**
     * 绑定手机
     *
     * @param uid
     * @param mobile
     * @param password
     * @param sms_code
     * @param session
     * @return
     */
    @Override
    public Result changeMobile(Integer uid, String mobile, String password, String sms_code, HttpSession session) {
        if (mobile != null) {
//            String code = (String) session.getAttribute(mobile);
            //redis 获取验证码
            String code = (String) redisTemplate.opsForValue().get(mobile);
            if (code != null && code.equals(sms_code)) {
                Users users = getById(uid);
                if (users != null && users.getPassword().equals(MD5.encrypt(password))) {
                    users.setMobile(mobile);
                    updateById(users);
                    //绑定成功后移除验证码
                    redisTemplate.delete(mobile);
                    return Result.success();
                } else {
                    return Result.fail("密码错误！");
                }
            } else {
                return Result.fail("验证码错误或验证码已失效！");
            }
        }
        return Result.fail("请输入手机号！");
    }

    /**
     * 退出登录
     *
     * @param uid
     * @return
     */
    @Override
    public Result logout(Integer uid) {
        return Result.success();
    }
}
